package com.sc.byahi.user.client.components;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Widget;
import com.sc.byahi.user.client.ProfileListView;
import com.sc.byahi.user.shared.constants.Config;

public class Pager extends Composite {

	private static ErrorUiBinder uiBinder = GWT.create(ErrorUiBinder.class);

	interface ErrorUiBinder extends UiBinder<Widget, Pager> {
	}

	@UiField
	Image first;
	@UiField
	Image prev;
	@UiField
	Image next;
	@UiField
	Image last;
	@UiField
	SpanElement description;

	List<Long> ids = new ArrayList<Long>();
	int begin = 0;// default
	int end = 0;// default
	/**
	 * So that caching can know what is the maximum size that it needs to hold.
	 */
	private int pageSize = Config.resultPageSize;// default

	int currPage = 1;// default
	int totalPages = 0;// default
	boolean isMap = false;
	ProfileListView view;

	public Pager(List<Long> ids, boolean isMap, ProfileListView view) {
		this();
		if (ids != null) {
			this.ids.addAll(ids);
		}
		this.isMap = isMap;
		this.view = view;
		reset();
		updateUIImagesAndText();
	}

	public Pager() {
		initWidget(uiBinder.createAndBindUi(this));
	}

	public boolean hasBefore() {
		return currPage > 1 ? true : false;
	}

	public boolean hasAfter() {
		return currPage < totalPages ? true : false;
	}

	@UiHandler("first")
	void onFirstClick(ClickEvent event) {
		if (hasBefore()) {
			setPageNum(1);
			updateUIImagesAndText();
			view.redrawTablePage();
		}
	}

	@UiHandler("prev")
	void onPrevClick(ClickEvent event) {
		if (hasBefore()) {
			setPageNum(currPage - 1);
			updateUIImagesAndText();
			view.redrawTablePage();
		}
	}

	@UiHandler("next")
	void onNextClick(ClickEvent event) {
		if (hasAfter()) {
			setPageNum(currPage + 1);
			updateUIImagesAndText();
			view.redrawTablePage();
		}
	}

	@UiHandler("last")
	void onLastClick(ClickEvent event) {
		if (hasAfter()) {
			setPageNum(totalPages);
			updateUIImagesAndText();
			view.redrawTablePage();
		}
	}

	private void updateUIImagesAndText() {
		if (hasBefore()) {
			prev.setUrl("/images/1leftarrow.png");
			first.setUrl("/images/2leftarrow.png");
		} else {
			prev.setUrl("/images/1leftarrowbw.png");
			first.setUrl("/images/2leftarrowbw.png");
		}
		if (hasAfter()) {
			next.setUrl("/images/1rightarrow.png");
			last.setUrl("/images/2rightarrow.png");
		} else {
			next.setUrl("/images/1rightarrowbw.png");
			last.setUrl("/images/2rightarrowbw.png");
		}
		String str = (begin + 1) + "-" + (end + 1) + " of " + ids.size();
		description.setInnerText(str);
	}

	/**
	 * For map, returns all ids, otherwise only paged values
	 * 
	 * @return
	 */
	public List<Long> getPage() {
		if (!isMap) {
			List<Long> subList = new ArrayList<Long>();
			subList.addAll(ids.subList(begin, end + 1));
			// NOTE: If you return sublist you are doomed.
			// return ids.subList(begin, end + 1);
			return subList;
		} else {
			return ids;
		}
	}

	public List<Long> prefetchNextPage() {
		List<Long> subList = new ArrayList<Long>();
		if (hasAfter()) {
			int nextPage = currPage + 1;
			int nextPageBegin = (nextPage - 1) * pageSize;
			int nextPageEnd = (nextPage * pageSize) - 1;
			int max = ids.size() - 1;
			if (nextPageEnd > max) nextPageEnd = max;
			subList.addAll(ids.subList(nextPageBegin, nextPageEnd + 1));
		}
		return subList;
	}

	/**
	 * Removes the id from list and when next paging request is done, new list is returned
	 * 
	 * @param profileId
	 */
	public void hideId(Long profileId) {
		ids.remove(profileId);
		calculateTotalPages();
		setPageNum(currPage);
		updateUIImagesAndText();

		//		if (currPage > totalPages) {// currPage not valid, change view
//			// so that begin, end etc text is changed
//			setPageNum(totalPages);
//			updateUIImagesAndText();
//		}
	}

	private void calculateTotalPages() {
		totalPages = new Double(Math.ceil((double) ids.size() / (double) pageSize)).intValue();
	}

	public void reset() {
		calculateTotalPages();
		setPageNum(1);
	}

	private void setPageNum(int page) {
		if (page > totalPages) {
			page = totalPages;
		}
		if (page < 1) {
			page = 1;
		}
		currPage = page;
		begin = (currPage - 1) * pageSize;
		end = (currPage * pageSize) - 1;
		int max = ids.size() - 1;
		if (end > max) end = max;
	}

}
